<template>
  <div></div>
</template>

<script>
import * as d3 from "d3";
export default {
  name: "forceDirected",
  props: {
    width: {
      type: Number
    },
    height: {
      type: Number
    }
  },
  mounted() {
    const width = this.width,height = this.height;
    // 在body里添加一个SVG画布
    let svg = d3
      .select(this.$el)
      .append("svg")
      .attr("width", width)
      .attr("height", height);
    let nodes = [
      { name: "桂林" },
      { name: "广州" },
      { name: "厦门" },
      { name: "杭州" },
      { name: "上海" },
      { name: "青岛" },
      { name: "天津" }
    ];
    let edges = [
      { source: 0, target: 1 },
      { source: 0, target: 2 },
      { source: 0, target: 3 },
      { source: 1, target: 4 },
      { source: 1, target: 5 },
      { source: 1, target: 6 }
    ];
    let force = d3
      .forceSimulation(nodes) // 指定节点数组
      .force("link", d3.forceLink()) // 使用指定的链接和默认参数创建新的链接力。如果未指定链接，则默认为空数组。
      .force("charge", d3.forceManyBody()) // d3.forceManyBody 使用默认参数创建新的多体力
      .force("center", d3.forceCenter(width / 2, height / 2)); // 定心
    force
      .force("link")
      .links(edges)
      .distance(150); // 每条边的长度
    // 添加连线
    let svg_edges = svg
      .selectAll("line")
      .data(edges)
      .enter()
      .append("line")
      .style("stroke", "#000")
      .style("stroke-width", 1);
    let color = d3.scaleOrdinal(d3.schemeCategory10);
    // 添加节点
    let svg_nodes = svg
      .selectAll("circle")
      .data(nodes)
      .enter()
      .append("circle")
      .attr("r", 20)
      .style("fill", function(d, i) {
        return color(i);
      })
      .call(
        d3
          .drag()
          .on("start", started)
          .on("drag", dragged)
          .on("end", ended)
      );
    // 添加描述节点的文字
    let svg_texts = svg
      .selectAll("text")
      .data(nodes)
      .enter()
      .append("text")
      .style("fill", "black")
      .attr("dx", 20)
      .attr("dy", 8)
      .text(function(d) {
        return d.name;
      });
    force.on("tick", function() {
      // 对于每一个时间间隔
      // 更新连线坐标
      svg_edges
        .attr("x1", function(d) {
          return d.source.x;
        })
        .attr("y1", function(d) {
          return d.source.y;
        })
        .attr("x2", function(d) {
          return d.target.x;
        })
        .attr("y2", function(d) {
          return d.target.y;
        });
      // 更新节点坐标
      svg_nodes
        .attr("cx", function(d) {
          return d.x;
        })
        .attr("cy", function(d) {
          return d.y;
        });
      // 更新文字坐标
      svg_texts
        .attr("x", function(d) {
          return d.x;
        })
        .attr("y", function(d) {
          return d.y;
        });
    });
    function started(d) {
      if (!d3.event.active) {
        force.alphaTarget(0.8).restart(); //设置衰减系数，对节点位置移动过程的模拟，数值越高移动越快，数值范围[0，1]
      }
      d.fx = d.x;
      d.fy = d.y;
    }
    function dragged(d) {
      d.fx = d3.event.x;
      d.fy = d3.event.y;
    }
    function ended(d) {
      if (!d3.event.active) {
        force.alphaTarget(0);
      }
      d.fx = null;
      d.fy = null;
    }
  }
};
</script>

<style scoped>
</style>

